{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "59f913c6-dd9a-48ab-b9e1-54077c63f658",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "./U1_G1_N30_L_L1_D0_20200408_2_Labeled.csv\n",
      "[0 1]\n",
      "./U1_G2_N30_L_L1_D0_20200408_2_Labeled.csv\n",
      "[0 2]\n",
      "./U1_G3_N30_L_L1_D0_20200408_2_Labeled.csv\n",
      "[0 3]\n",
      "./U1_G1_N10_L_L1_D0_20200408_1_Labeled.csv\n",
      "[0 1]\n",
      "./U1_G2_N10_L_L1_D0_20200408_1_Labeled.csv\n",
      "[0 2]\n",
      "./U1_G3_N10_L_L1_D0_20200408_1_Labeled.csv\n",
      "[0 3]\n",
      "Training segments: 183\n",
      "Training Segment 1: 6414\n",
      "Training Segment 2: 3504\n",
      "Training Segment 3: 1214\n",
      "Training Segment 4: 2960\n",
      "Training Segment 5: 974\n",
      "Training Segment 6: 3024\n",
      "Training Segment 7: 814\n",
      "Training Segment 8: 3248\n",
      "Training Segment 9: 734\n",
      "Training Segment 10: 2928\n",
      "Training Segment 11: 782\n",
      "Training Segment 12: 2480\n",
      "Training Segment 13: 1102\n",
      "Training Segment 14: 2656\n",
      "Training Segment 15: 750\n",
      "Training Segment 16: 2672\n",
      "Training Segment 17: 606\n",
      "Training Segment 18: 3200\n",
      "Training Segment 19: 350\n",
      "Training Segment 20: 3392\n",
      "Training Segment 21: 878\n",
      "Training Segment 22: 3136\n",
      "Training Segment 23: 686\n",
      "Training Segment 24: 3408\n",
      "Training Segment 25: 558\n",
      "Training Segment 26: 3056\n",
      "Training Segment 27: 798\n",
      "Training Segment 28: 3472\n",
      "Training Segment 29: 670\n",
      "Training Segment 30: 3328\n",
      "Training Segment 31: 446\n",
      "Training Segment 32: 3472\n",
      "Training Segment 33: 798\n",
      "Training Segment 34: 2960\n",
      "Training Segment 35: 1438\n",
      "Training Segment 36: 3184\n",
      "Training Segment 37: 1134\n",
      "Training Segment 38: 2736\n",
      "Training Segment 39: 718\n",
      "Training Segment 40: 3200\n",
      "Training Segment 41: 942\n",
      "Training Segment 42: 3168\n",
      "Training Segment 43: 1454\n",
      "Training Segment 44: 2848\n",
      "Training Segment 45: 1342\n",
      "Training Segment 46: 3168\n",
      "Training Segment 47: 910\n",
      "Training Segment 48: 2624\n",
      "Training Segment 49: 1198\n",
      "Training Segment 50: 3024\n",
      "Training Segment 51: 974\n",
      "Training Segment 52: 3088\n",
      "Training Segment 53: 974\n",
      "Training Segment 54: 3200\n",
      "Training Segment 55: 558\n",
      "Training Segment 56: 3408\n",
      "Training Segment 57: 798\n",
      "Training Segment 58: 2928\n",
      "Training Segment 59: 1038\n",
      "Training Segment 60: 3424\n",
      "Training Segment 61: 7663\n",
      "Training Segment 62: 7870\n",
      "Training Segment 63: 3632\n",
      "Training Segment 64: 1502\n",
      "Training Segment 65: 4240\n",
      "Training Segment 66: 1102\n",
      "Training Segment 67: 3392\n",
      "Training Segment 68: 1582\n",
      "Training Segment 69: 4096\n",
      "Training Segment 70: 1822\n",
      "Training Segment 71: 3520\n",
      "Training Segment 72: 1470\n",
      "Training Segment 73: 3936\n",
      "Training Segment 74: 1118\n",
      "Training Segment 75: 4480\n",
      "Training Segment 76: 1246\n",
      "Training Segment 77: 3552\n",
      "Training Segment 78: 1646\n",
      "Training Segment 79: 3824\n",
      "Training Segment 80: 2094\n",
      "Training Segment 81: 3440\n",
      "Training Segment 82: 2270\n",
      "Training Segment 83: 4160\n",
      "Training Segment 84: 1630\n",
      "Training Segment 85: 4096\n",
      "Training Segment 86: 1630\n",
      "Training Segment 87: 4256\n",
      "Training Segment 88: 1774\n",
      "Training Segment 89: 3472\n",
      "Training Segment 90: 2270\n",
      "Training Segment 91: 3600\n",
      "Training Segment 92: 2110\n",
      "Training Segment 93: 3696\n",
      "Training Segment 94: 2190\n",
      "Training Segment 95: 3888\n",
      "Training Segment 96: 1902\n",
      "Training Segment 97: 4208\n",
      "Training Segment 98: 1886\n",
      "Training Segment 99: 4256\n",
      "Training Segment 100: 2030\n",
      "Training Segment 101: 4048\n",
      "Training Segment 102: 2478\n",
      "Training Segment 103: 4000\n",
      "Training Segment 104: 2238\n",
      "Training Segment 105: 4224\n",
      "Training Segment 106: 3022\n",
      "Training Segment 107: 4480\n",
      "Training Segment 108: 1310\n",
      "Training Segment 109: 4208\n",
      "Training Segment 110: 2174\n",
      "Training Segment 111: 4096\n",
      "Training Segment 112: 2238\n",
      "Training Segment 113: 4144\n",
      "Training Segment 114: 2766\n",
      "Training Segment 115: 4832\n",
      "Training Segment 116: 1454\n",
      "Training Segment 117: 4224\n",
      "Training Segment 118: 4526\n",
      "Training Segment 119: 4336\n",
      "Training Segment 120: 3438\n",
      "Training Segment 121: 4464\n",
      "Training Segment 122: 9807\n",
      "Training Segment 123: 17694\n",
      "Training Segment 124: 2512\n",
      "Training Segment 125: 1758\n",
      "Training Segment 126: 2192\n",
      "Training Segment 127: 1150\n",
      "Training Segment 128: 2592\n",
      "Training Segment 129: 1694\n",
      "Training Segment 130: 2176\n",
      "Training Segment 131: 1198\n",
      "Training Segment 132: 2144\n",
      "Training Segment 133: 1710\n",
      "Training Segment 134: 2032\n",
      "Training Segment 135: 2222\n",
      "Training Segment 136: 2256\n",
      "Training Segment 137: 2110\n",
      "Training Segment 138: 1760\n",
      "Training Segment 139: 2718\n",
      "Training Segment 140: 2176\n",
      "Training Segment 141: 2110\n",
      "Training Segment 142: 2112\n",
      "Training Segment 143: 2798\n",
      "Training Segment 144: 2400\n",
      "Training Segment 145: 2558\n",
      "Training Segment 146: 2208\n",
      "Training Segment 147: 2926\n",
      "Training Segment 148: 2496\n",
      "Training Segment 149: 2590\n",
      "Training Segment 150: 2448\n",
      "Training Segment 151: 2526\n",
      "Training Segment 152: 2416\n",
      "Training Segment 153: 3006\n",
      "Training Segment 154: 2320\n",
      "Training Segment 155: 3518\n",
      "Training Segment 156: 2032\n",
      "Training Segment 157: 5406\n",
      "Training Segment 158: 2240\n",
      "Training Segment 159: 5278\n",
      "Training Segment 160: 2304\n",
      "Training Segment 161: 8094\n",
      "Training Segment 162: 2192\n",
      "Training Segment 163: 22366\n",
      "Training Segment 164: 2352\n",
      "Training Segment 165: 1726\n",
      "Training Segment 166: 2768\n",
      "Training Segment 167: 2430\n",
      "Training Segment 168: 2176\n",
      "Training Segment 169: 3166\n",
      "Training Segment 170: 2208\n",
      "Training Segment 171: 3950\n",
      "Training Segment 172: 3360\n",
      "Training Segment 173: 3278\n",
      "Training Segment 174: 2672\n",
      "Training Segment 175: 2558\n",
      "Training Segment 176: 2400\n",
      "Training Segment 177: 3630\n",
      "Training Segment 178: 1712\n",
      "Training Segment 179: 3838\n",
      "Training Segment 180: 2240\n",
      "Training Segment 181: 2606\n",
      "Training Segment 182: 2416\n",
      "Training Segment 183: 8559\n",
      "Testing segments: 63\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "# Define training and testing files\n",
    "training_files = [\n",
    "    './U1_G1_N30_L_L1_D0_20200408_2_Labeled.csv',\n",
    "    './U1_G2_N30_L_L1_D0_20200408_2_Labeled.csv',\n",
    "    './U1_G3_N30_L_L1_D0_20200408_2_Labeled.csv']\n",
    "\n",
    "testing_files = [\n",
    "    './U1_G1_N10_L_L1_D0_20200408_1_Labeled.csv',\n",
    "    './U1_G2_N10_L_L1_D0_20200408_1_Labeled.csv',\n",
    "    './U1_G3_N10_L_L1_D0_20200408_1_Labeled.csv'\n",
    "]\n",
    "\n",
    "# Function to read and process CSV files\n",
    "def read_csv_file(file_path):\n",
    "    print(file_path)\n",
    "    df = pd.read_csv(file_path)\n",
    "    csi = df.iloc[:, 2:].values  # All columns except 'timestamp' and 'label'\n",
    "    label = df['label'].values # 0: static, 1: up, 2: down, 3: left, 4: right\n",
    "    timestamp = df['timestamp'].values\n",
    "    print(np.unique(label))\n",
    "    return csi, label, timestamp\n",
    "\n",
    "def segment_signals(csi, label, timestamp):\n",
    "    segments = [] # Store segments\n",
    "    segment_label = label[0] # Initialize segment label\n",
    "    segment_start = 0 # Initialize segment start index\n",
    "\n",
    "    for i in range(len(label)): # Iterate through all labels\n",
    "        if label[i] != segment_label: # If the label is different from the current segment label\n",
    "            segments.append((csi[segment_start:i-1], segment_label, timestamp[segment_start:i-1])) # Append the current segment to the segments list\n",
    "            segment_start = i # Update the segment start index\n",
    "            segment_label = label[i] # Update the segment label\n",
    "\n",
    "    segments.append((csi[segment_start:], segment_label, timestamp[segment_start:])) # Append the last segment to the segments list\n",
    "    return segments\n",
    "\n",
    "# Define training and testing segments\n",
    "training_segments = []\n",
    "testing_segments = []\n",
    "\n",
    "# Read and process training files\n",
    "for file in training_files:\n",
    "    s, y, t = read_csv_file(file)\n",
    "    training_segments.extend(segment_signals(s, y, t))\n",
    "\n",
    "# Read and process testing files\n",
    "for file in testing_files:\n",
    "    s, y, t = read_csv_file(file)\n",
    "    testing_segments.extend(segment_signals(s, y, t))\n",
    "\n",
    "# Print sizes of the training segments and testing segments\n",
    "print(f\"Training segments: {len(training_segments)}\")\n",
    "\n",
    "# Print length of all training segments\n",
    "for i, (s, y, t) in enumerate(training_segments):\n",
    "    print(f\"Training Segment {i + 1}: {len(s)}\")\n",
    "\n",
    "# Print size of the testing segments\n",
    "print(f\"Testing segments: {len(testing_segments)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "193c0ca7-e138-4c73-b12b-6b351580801e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from scipy.stats import kurtosis\n",
    "from scipy.stats import skew\n",
    "\n",
    "# Extract features of training segments\n",
    "def extract_features(s):\n",
    "    ''' \n",
    "    Extract features of each segment\n",
    "    features include:\n",
    "    - mean\n",
    "    - std\n",
    "    - max\n",
    "    - min\n",
    "    - median\n",
    "    - kurtosis\n",
    "    - skew\n",
    "    \n",
    "    Input:\n",
    "    s: segment (N*30) in training_segments or testing_segments\n",
    "    \n",
    "    Output:\n",
    "    x: 1-D vector (8*30)\n",
    "    '''\n",
    "    x = []\n",
    "    x.extend(np.mean(s, axis=0))\n",
    "    x.extend(np.std(s, axis=0))\n",
    "    x.extend(np.max(s, axis=0))\n",
    "    x.extend(np.min(s, axis=0))\n",
    "    x.extend(np.median(s, axis=0))\n",
    "    x.extend(kurtosis(s, axis=0))\n",
    "    x.extend(skew(s, axis=0))\n",
    "\n",
    "    return np.array(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "80c63b03-f2ae-4c3f-9742-2455cb6ca6e8",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\PC\\AppData\\Local\\Temp\\ipykernel_5412\\496475029.py:16: UserWarning: Creating a tensor from a list of numpy.ndarrays is extremely slow. Please consider converting the list to a single numpy.ndarray with numpy.array() before converting to a tensor. (Triggered internally at C:\\b\\abs_e1nmgx0bk6\\croot\\pytorch-select_1725478824526\\work\\torch\\csrc\\utils\\tensor_new.cpp:277.)\n",
      "  trX = torch.tensor(trX, dtype=torch.float32) # Convert trX to tensor\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "from torch.utils.data import DataLoader, TensorDataset\n",
    "\n",
    "def one_hot_collate(batch):\n",
    "    data = torch.stack([item[0] for item in batch])\n",
    "    labels = torch.tensor([item[1] for item in batch])\n",
    "    \n",
    "    one_hot_labels = torch.zeros(labels.size(0), 4)  # 4 classes\n",
    "    one_hot_labels.scatter_(1, labels.unsqueeze(1), 1)\n",
    "    return data, one_hot_labels\n",
    "\n",
    "batch_size = 4\n",
    "\n",
    "# Build training dataset\n",
    "trX = [extract_features(s) for s, _, _ in training_segments] # Extract features of training segments\n",
    "trX = torch.tensor(trX, dtype=torch.float32) # Convert trX to tensor\n",
    "trY = [y for _, y, _ in training_segments] # Extract labels of training segments\n",
    "trY = torch.tensor(trY) # Convert trY to tensor\n",
    "\n",
    "# Build testing dataset\n",
    "teX = [extract_features(s) for s, _, _ in testing_segments] # Extract features of testing segments\n",
    "teX = torch.tensor(teX, dtype=torch.float32) # Convert teX to tensor\n",
    "teY = [y for _, y, _ in testing_segments] # Extract labels of testing segments\n",
    "teY = torch.tensor(teY) # Convert teY to tensor\n",
    "\n",
    "# Normalize trX and teX\n",
    "# Calculate mean and standard deviation from the training data\n",
    "mean = trX.mean(dim=0)\n",
    "std = trX.std(dim=0)\n",
    "\n",
    "# Normalize training data\n",
    "trX = (trX - mean) / std\n",
    "\n",
    "# Normalize testing data using training mean and std\n",
    "teX = (teX - mean) / std\n",
    "\n",
    "# Build Dataset\n",
    "trDataset = TensorDataset(trX, trY) # Create training dataset\n",
    "teDataset = TensorDataset(teX, teY) # Create testing dataset\n",
    "\n",
    "# Build loader\n",
    "trLoader = DataLoader(trDataset, batch_size=batch_size, shuffle=True, num_workers=0, collate_fn=one_hot_collate) # Create training dataloader\n",
    "teLoader = DataLoader(teDataset, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate) # Create testing dataloader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "ce743cd6-ca04-4ea0-87ff-ca2ead8933c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch.nn as nn\n",
    "\n",
    "class FNN(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size, num_classes):\n",
    "        super(FNN, self).__init__()\n",
    "        self.fc1 = nn.Linear(input_size, hidden_size)\n",
    "        self.relu1 = nn.ReLU()\n",
    "        self.fc2 = nn.Linear(hidden_size, hidden_size)\n",
    "        self.relu2 = nn.ReLU()\n",
    "        self.fc3 = nn.Linear(hidden_size, num_classes)\n",
    "        self.softmax = nn.Softmax(dim=1)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = self.fc1(x)\n",
    "        x = self.relu1(x)\n",
    "        x = self.fc2(x)\n",
    "        x = self.relu2(x)\n",
    "        x = self.fc3(x)\n",
    "        out = self.softmax(x)\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "6faa17e5-cb8d-47a2-9822-b953f7921c3e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "FNN(\n",
      "  (fc1): Linear(in_features=210, out_features=10, bias=True)\n",
      "  (relu1): ReLU()\n",
      "  (fc2): Linear(in_features=10, out_features=10, bias=True)\n",
      "  (relu2): ReLU()\n",
      "  (fc3): Linear(in_features=10, out_features=4, bias=True)\n",
      "  (softmax): Softmax(dim=1)\n",
      ")\n",
      "Epoch [1/200], Train Loss: 1.2818, CV Loss: 1.1669\n",
      "Epoch [2/200], Train Loss: 1.1188, CV Loss: 1.0753\n",
      "Epoch [3/200], Train Loss: 1.0531, CV Loss: 1.0616\n",
      "Epoch [4/200], Train Loss: 1.0232, CV Loss: 1.0630\n",
      "Epoch [5/200], Train Loss: 0.9940, CV Loss: 1.0687\n",
      "Epoch [6/200], Train Loss: 0.9664, CV Loss: 1.0825\n",
      "Epoch [7/200], Train Loss: 0.9441, CV Loss: 1.0786\n",
      "Epoch [8/200], Train Loss: 0.9277, CV Loss: 1.0743\n",
      "Epoch [9/200], Train Loss: 0.9174, CV Loss: 1.0754\n",
      "Epoch [10/200], Train Loss: 0.8999, CV Loss: 1.0663\n",
      "Epoch [11/200], Train Loss: 0.8838, CV Loss: 1.0573\n",
      "Epoch [12/200], Train Loss: 0.8657, CV Loss: 1.0532\n",
      "Epoch [13/200], Train Loss: 0.8529, CV Loss: 1.0474\n",
      "Epoch [14/200], Train Loss: 0.8340, CV Loss: 1.0433\n",
      "Epoch [15/200], Train Loss: 0.8233, CV Loss: 1.0356\n",
      "Epoch [16/200], Train Loss: 0.8151, CV Loss: 1.0333\n",
      "Epoch [17/200], Train Loss: 0.8056, CV Loss: 1.0381\n",
      "Epoch [18/200], Train Loss: 0.7996, CV Loss: 1.0384\n",
      "Epoch [19/200], Train Loss: 0.7957, CV Loss: 1.0314\n",
      "Epoch [20/200], Train Loss: 0.7912, CV Loss: 1.0396\n",
      "Epoch [21/200], Train Loss: 0.7883, CV Loss: 1.0397\n",
      "Epoch [22/200], Train Loss: 0.7841, CV Loss: 1.0402\n",
      "Epoch [23/200], Train Loss: 0.7819, CV Loss: 1.0422\n",
      "Epoch [24/200], Train Loss: 0.7791, CV Loss: 1.0457\n",
      "Epoch [25/200], Train Loss: 0.7768, CV Loss: 1.0447\n",
      "Epoch [26/200], Train Loss: 0.7750, CV Loss: 1.0443\n",
      "Epoch [27/200], Train Loss: 0.7733, CV Loss: 1.0495\n",
      "Epoch [28/200], Train Loss: 0.7721, CV Loss: 1.0526\n",
      "Epoch [29/200], Train Loss: 0.7707, CV Loss: 1.0520\n",
      "Epoch [30/200], Train Loss: 0.7694, CV Loss: 1.0486\n",
      "Epoch [31/200], Train Loss: 0.7695, CV Loss: 1.0427\n",
      "Epoch [32/200], Train Loss: 0.7657, CV Loss: 1.0478\n",
      "Epoch [33/200], Train Loss: 0.7641, CV Loss: 1.0374\n",
      "Epoch [34/200], Train Loss: 0.7625, CV Loss: 1.0416\n",
      "Epoch [35/200], Train Loss: 0.7610, CV Loss: 1.0442\n",
      "Epoch [36/200], Train Loss: 0.7608, CV Loss: 1.0406\n",
      "Epoch [37/200], Train Loss: 0.7597, CV Loss: 1.0472\n",
      "Epoch [38/200], Train Loss: 0.7586, CV Loss: 1.0453\n",
      "Epoch [39/200], Train Loss: 0.7584, CV Loss: 1.0314\n",
      "Epoch [40/200], Train Loss: 0.7577, CV Loss: 1.0427\n",
      "Epoch [41/200], Train Loss: 0.7566, CV Loss: 1.0357\n",
      "Epoch [42/200], Train Loss: 0.7560, CV Loss: 1.0383\n",
      "Epoch [43/200], Train Loss: 0.7550, CV Loss: 1.0350\n",
      "Epoch [44/200], Train Loss: 0.7541, CV Loss: 1.0376\n",
      "Epoch [45/200], Train Loss: 0.7534, CV Loss: 1.0364\n",
      "Epoch [46/200], Train Loss: 0.7528, CV Loss: 1.0332\n",
      "Epoch [47/200], Train Loss: 0.7523, CV Loss: 1.0291\n",
      "Epoch [48/200], Train Loss: 0.7523, CV Loss: 1.0316\n",
      "Epoch [49/200], Train Loss: 0.7517, CV Loss: 1.0295\n",
      "Epoch [50/200], Train Loss: 0.7515, CV Loss: 1.0292\n",
      "Epoch [51/200], Train Loss: 0.7513, CV Loss: 1.0288\n",
      "Epoch [52/200], Train Loss: 0.7510, CV Loss: 1.0297\n",
      "Epoch [53/200], Train Loss: 0.7509, CV Loss: 1.0320\n",
      "Epoch [54/200], Train Loss: 0.7507, CV Loss: 1.0303\n",
      "Epoch [55/200], Train Loss: 0.7506, CV Loss: 1.0309\n",
      "Epoch [56/200], Train Loss: 0.7505, CV Loss: 1.0335\n",
      "Epoch [57/200], Train Loss: 0.7504, CV Loss: 1.0300\n",
      "Epoch [58/200], Train Loss: 0.7502, CV Loss: 1.0283\n",
      "Epoch [59/200], Train Loss: 0.7502, CV Loss: 1.0273\n",
      "Epoch [60/200], Train Loss: 0.7501, CV Loss: 1.0293\n",
      "Epoch [61/200], Train Loss: 0.7500, CV Loss: 1.0302\n",
      "Epoch [62/200], Train Loss: 0.7499, CV Loss: 1.0249\n",
      "Epoch [63/200], Train Loss: 0.7499, CV Loss: 1.0236\n",
      "Epoch [64/200], Train Loss: 0.7498, CV Loss: 1.0245\n",
      "Epoch [65/200], Train Loss: 0.7497, CV Loss: 1.0255\n",
      "Epoch [66/200], Train Loss: 0.7497, CV Loss: 1.0241\n",
      "Epoch [67/200], Train Loss: 0.7496, CV Loss: 1.0261\n",
      "Epoch [68/200], Train Loss: 0.7496, CV Loss: 1.0265\n",
      "Epoch [69/200], Train Loss: 0.7495, CV Loss: 1.0266\n",
      "Epoch [70/200], Train Loss: 0.7495, CV Loss: 1.0218\n",
      "Epoch [71/200], Train Loss: 0.7495, CV Loss: 1.0264\n",
      "Epoch [72/200], Train Loss: 0.7495, CV Loss: 1.0232\n",
      "Epoch [73/200], Train Loss: 0.7494, CV Loss: 1.0233\n",
      "Epoch [74/200], Train Loss: 0.7494, CV Loss: 1.0234\n",
      "Epoch [75/200], Train Loss: 0.7494, CV Loss: 1.0207\n",
      "Epoch [76/200], Train Loss: 0.7495, CV Loss: 1.0180\n",
      "Epoch [77/200], Train Loss: 0.7494, CV Loss: 1.0204\n",
      "Epoch [78/200], Train Loss: 0.7495, CV Loss: 1.0173\n",
      "Epoch [79/200], Train Loss: 0.7493, CV Loss: 1.0216\n",
      "Epoch [80/200], Train Loss: 0.7493, CV Loss: 1.0185\n",
      "Epoch [81/200], Train Loss: 0.7494, CV Loss: 1.0208\n",
      "Epoch [82/200], Train Loss: 0.7492, CV Loss: 1.0146\n",
      "Epoch [83/200], Train Loss: 0.7493, CV Loss: 1.0177\n",
      "Epoch [84/200], Train Loss: 0.7493, CV Loss: 1.0159\n",
      "Epoch [85/200], Train Loss: 0.7493, CV Loss: 1.0186\n",
      "Epoch [86/200], Train Loss: 0.7492, CV Loss: 1.0181\n",
      "Epoch [87/200], Train Loss: 0.7493, CV Loss: 1.0178\n",
      "Epoch [88/200], Train Loss: 0.7491, CV Loss: 1.0192\n",
      "Epoch [89/200], Train Loss: 0.7493, CV Loss: 1.0189\n",
      "Epoch [90/200], Train Loss: 0.7491, CV Loss: 1.0179\n",
      "Epoch [91/200], Train Loss: 0.7492, CV Loss: 1.0191\n",
      "Epoch [92/200], Train Loss: 0.7493, CV Loss: 1.0162\n",
      "Epoch [93/200], Train Loss: 0.7492, CV Loss: 1.0196\n",
      "Epoch [94/200], Train Loss: 0.7493, CV Loss: 1.0172\n",
      "Epoch [95/200], Train Loss: 0.7491, CV Loss: 1.0208\n",
      "Epoch [96/200], Train Loss: 0.7492, CV Loss: 1.0161\n",
      "Epoch [97/200], Train Loss: 0.7491, CV Loss: 1.0140\n",
      "Epoch [98/200], Train Loss: 0.7492, CV Loss: 1.0164\n",
      "Epoch [99/200], Train Loss: 0.7490, CV Loss: 1.0161\n",
      "Epoch [100/200], Train Loss: 0.7493, CV Loss: 1.0159\n",
      "Epoch [101/200], Train Loss: 0.7489, CV Loss: 1.0122\n",
      "Epoch [102/200], Train Loss: 0.7491, CV Loss: 1.0133\n",
      "Epoch [103/200], Train Loss: 0.7492, CV Loss: 1.0110\n",
      "Epoch [104/200], Train Loss: 0.7490, CV Loss: 1.0145\n",
      "Epoch [105/200], Train Loss: 0.7492, CV Loss: 1.0166\n",
      "Epoch [106/200], Train Loss: 0.7489, CV Loss: 1.0102\n",
      "Epoch [107/200], Train Loss: 0.7492, CV Loss: 1.0144\n",
      "Epoch [108/200], Train Loss: 0.7489, CV Loss: 1.0093\n",
      "Epoch [109/200], Train Loss: 0.7492, CV Loss: 1.0053\n",
      "Epoch [110/200], Train Loss: 0.7488, CV Loss: 1.0092\n",
      "Epoch [111/200], Train Loss: 0.7490, CV Loss: 1.0071\n",
      "Epoch [112/200], Train Loss: 0.7492, CV Loss: 1.0081\n",
      "Epoch [113/200], Train Loss: 0.7491, CV Loss: 1.0132\n",
      "Epoch [114/200], Train Loss: 0.7492, CV Loss: 1.0150\n",
      "Epoch [115/200], Train Loss: 0.7488, CV Loss: 1.0135\n",
      "Epoch [116/200], Train Loss: 0.7489, CV Loss: 1.0099\n",
      "Epoch [117/200], Train Loss: 0.7492, CV Loss: 1.0058\n",
      "Epoch [118/200], Train Loss: 0.7489, CV Loss: 1.0060\n",
      "Epoch [119/200], Train Loss: 0.7493, CV Loss: 1.0137\n",
      "Epoch [120/200], Train Loss: 0.7491, CV Loss: 1.0079\n",
      "Epoch [121/200], Train Loss: 0.7489, CV Loss: 1.0131\n",
      "Epoch [122/200], Train Loss: 0.7492, CV Loss: 1.0148\n",
      "Epoch [123/200], Train Loss: 0.7489, CV Loss: 1.0154\n",
      "Epoch [124/200], Train Loss: 0.7492, CV Loss: 1.0224\n",
      "Epoch [125/200], Train Loss: 0.7489, CV Loss: 1.0029\n",
      "Epoch [126/200], Train Loss: 0.7492, CV Loss: 1.0193\n",
      "Epoch [127/200], Train Loss: 0.7483, CV Loss: 1.0548\n",
      "Epoch [128/200], Train Loss: 0.7450, CV Loss: 1.0186\n",
      "Epoch [129/200], Train Loss: 0.7457, CV Loss: 1.0330\n",
      "Epoch [130/200], Train Loss: 0.7439, CV Loss: 1.0234\n",
      "Epoch [131/200], Train Loss: 0.7438, CV Loss: 1.0220\n",
      "Epoch [132/200], Train Loss: 0.7438, CV Loss: 1.0193\n",
      "Epoch [133/200], Train Loss: 0.7438, CV Loss: 1.0181\n",
      "Epoch [134/200], Train Loss: 0.7438, CV Loss: 1.0169\n",
      "Epoch [135/200], Train Loss: 0.7438, CV Loss: 1.0158\n",
      "Epoch [136/200], Train Loss: 0.7438, CV Loss: 1.0140\n",
      "Epoch [137/200], Train Loss: 0.7438, CV Loss: 1.0132\n",
      "Epoch [138/200], Train Loss: 0.7438, CV Loss: 1.0130\n",
      "Epoch [139/200], Train Loss: 0.7438, CV Loss: 1.0124\n",
      "Epoch [140/200], Train Loss: 0.7438, CV Loss: 1.0118\n",
      "Epoch [141/200], Train Loss: 0.7438, CV Loss: 1.0103\n",
      "Epoch [142/200], Train Loss: 0.7438, CV Loss: 1.0108\n",
      "Epoch [143/200], Train Loss: 0.7438, CV Loss: 1.0101\n",
      "Epoch [144/200], Train Loss: 0.7438, CV Loss: 1.0094\n",
      "Epoch [145/200], Train Loss: 0.7437, CV Loss: 1.0089\n",
      "Epoch [146/200], Train Loss: 0.7437, CV Loss: 1.0082\n",
      "Epoch [147/200], Train Loss: 0.7437, CV Loss: 1.0083\n",
      "Epoch [148/200], Train Loss: 0.7437, CV Loss: 1.0082\n",
      "Epoch [149/200], Train Loss: 0.7437, CV Loss: 1.0078\n",
      "Epoch [150/200], Train Loss: 0.7437, CV Loss: 1.0071\n",
      "Epoch [151/200], Train Loss: 0.7437, CV Loss: 1.0067\n",
      "Epoch [152/200], Train Loss: 0.7437, CV Loss: 1.0069\n",
      "Epoch [153/200], Train Loss: 0.7437, CV Loss: 1.0066\n",
      "Epoch [154/200], Train Loss: 0.7437, CV Loss: 1.0058\n",
      "Epoch [155/200], Train Loss: 0.7437, CV Loss: 1.0052\n",
      "Epoch [156/200], Train Loss: 0.7437, CV Loss: 1.0055\n",
      "Epoch [157/200], Train Loss: 0.7437, CV Loss: 1.0045\n",
      "Epoch [158/200], Train Loss: 0.7437, CV Loss: 1.0042\n",
      "Epoch [159/200], Train Loss: 0.7437, CV Loss: 1.0043\n",
      "Epoch [160/200], Train Loss: 0.7437, CV Loss: 1.0040\n",
      "Epoch [161/200], Train Loss: 0.7437, CV Loss: 1.0037\n",
      "Epoch [162/200], Train Loss: 0.7437, CV Loss: 1.0037\n",
      "Epoch [163/200], Train Loss: 0.7437, CV Loss: 1.0034\n",
      "Epoch [164/200], Train Loss: 0.7437, CV Loss: 1.0029\n",
      "Epoch [165/200], Train Loss: 0.7437, CV Loss: 1.0024\n",
      "Epoch [166/200], Train Loss: 0.7437, CV Loss: 1.0025\n",
      "Epoch [167/200], Train Loss: 0.7437, CV Loss: 1.0026\n",
      "Epoch [168/200], Train Loss: 0.7437, CV Loss: 1.0023\n",
      "Epoch [169/200], Train Loss: 0.7437, CV Loss: 1.0025\n",
      "Epoch [170/200], Train Loss: 0.7437, CV Loss: 1.0018\n",
      "Epoch [171/200], Train Loss: 0.7437, CV Loss: 1.0021\n",
      "Epoch [172/200], Train Loss: 0.7437, CV Loss: 1.0017\n",
      "Epoch [173/200], Train Loss: 0.7437, CV Loss: 1.0012\n",
      "Epoch [174/200], Train Loss: 0.7437, CV Loss: 1.0011\n",
      "Epoch [175/200], Train Loss: 0.7437, CV Loss: 1.0008\n",
      "Epoch [176/200], Train Loss: 0.7437, CV Loss: 1.0010\n",
      "Epoch [177/200], Train Loss: 0.7437, CV Loss: 1.0007\n",
      "Epoch [178/200], Train Loss: 0.7437, CV Loss: 1.0001\n",
      "Epoch [179/200], Train Loss: 0.7437, CV Loss: 1.0004\n",
      "Epoch [180/200], Train Loss: 0.7437, CV Loss: 1.0001\n",
      "Epoch [181/200], Train Loss: 0.7437, CV Loss: 0.9999\n",
      "Epoch [182/200], Train Loss: 0.7437, CV Loss: 0.9992\n",
      "Epoch [183/200], Train Loss: 0.7437, CV Loss: 0.9989\n",
      "Epoch [184/200], Train Loss: 0.7437, CV Loss: 0.9987\n",
      "Epoch [185/200], Train Loss: 0.7437, CV Loss: 0.9987\n",
      "Epoch [186/200], Train Loss: 0.7437, CV Loss: 0.9986\n",
      "Epoch [187/200], Train Loss: 0.7437, CV Loss: 0.9982\n",
      "Epoch [188/200], Train Loss: 0.7437, CV Loss: 0.9982\n",
      "Epoch [189/200], Train Loss: 0.7437, CV Loss: 0.9982\n",
      "Epoch [190/200], Train Loss: 0.7437, CV Loss: 0.9978\n",
      "Epoch [191/200], Train Loss: 0.7437, CV Loss: 0.9976\n",
      "Epoch [192/200], Train Loss: 0.7437, CV Loss: 0.9974\n",
      "Epoch [193/200], Train Loss: 0.7437, CV Loss: 0.9975\n",
      "Epoch [194/200], Train Loss: 0.7437, CV Loss: 0.9968\n",
      "Epoch [195/200], Train Loss: 0.7437, CV Loss: 0.9971\n",
      "Epoch [196/200], Train Loss: 0.7437, CV Loss: 0.9970\n",
      "Epoch [197/200], Train Loss: 0.7437, CV Loss: 0.9966\n",
      "Epoch [198/200], Train Loss: 0.7437, CV Loss: 0.9960\n",
      "Epoch [199/200], Train Loss: 0.7437, CV Loss: 0.9961\n",
      "Epoch [200/200], Train Loss: 0.7437, CV Loss: 0.9959\n"
     ]
    }
   ],
   "source": [
    "# Define the model parameters\n",
    "hidden_size = 10\n",
    "\n",
    "# Instantiate the model\n",
    "input_size = trX.shape[1]\n",
    "num_classes = 4 # 3 movements and static\n",
    "model = FNN(input_size, hidden_size, num_classes)\n",
    "print(model)\n",
    "\n",
    "# Define loss function and optimizer\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.Adam(model.parameters())\n",
    "\n",
    "# Lists to store losses\n",
    "train_losses = []\n",
    "te_losses = []\n",
    "\n",
    "# Number of epochs\n",
    "num_epochs = 200\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    model.train()\n",
    "    batch_losses = []\n",
    "    \n",
    "    for batch_x, batch_y in trLoader:\n",
    "        # Forward pass\n",
    "        outputs = model(batch_x)\n",
    "        loss = criterion(outputs, batch_y)\n",
    "        \n",
    "        # Backward pass and optimize\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        \n",
    "        batch_losses.append(loss.item())\n",
    "    \n",
    "    # Calculate average training loss for this epoch\n",
    "    avg_train_loss = sum(batch_losses) / len(batch_losses)\n",
    "    train_losses.append(avg_train_loss)\n",
    "    \n",
    "    # Evaluate on cross-validation set\n",
    "    model.eval()\n",
    "    te_batch_losses = []\n",
    "    with torch.no_grad():\n",
    "        for te_x, te_y in teLoader:\n",
    "            te_outputs = model(te_x)\n",
    "            te_loss = criterion(te_outputs, te_y)\n",
    "            te_batch_losses.append(te_loss.item())\n",
    "    \n",
    "    avg_te_loss = sum(te_batch_losses) / len(te_batch_losses)\n",
    "    te_losses.append(avg_te_loss)\n",
    "    \n",
    "    print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {avg_train_loss:.4f}, CV Loss: {avg_te_loss:.4f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "9076594e-98b8-4e2b-8fe6-9d9571f7e77e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy on training set: 100.00%\n",
      "Accuracy on cross-validation set: 74.60%\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA04AAAHACAYAAACVhTgAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABsq0lEQVR4nO3dd3hUZfrG8XtmMqmkEEoKhCLSmwiiYAEsFLu4VlRwVcSOWFl/KrZF17WsDXddFTuIbS1YQAXsdKSDEggloZNeJjPn98c7mRAIaSQ5k/D9XNdcmTlzZuaZ4RjnzvO+73FYlmUJAAAAAHBITrsLAAAAAIBgR3ACAAAAgEoQnAAAAACgEgQnAAAAAKgEwQkAAAAAKkFwAgAAAIBKEJwAAAAAoBIEJwAAAACoRIjdBdQ3n8+nbdu2KTo6Wg6Hw+5yAAAAANjEsixlZ2crOTlZTmfFPaUjLjht27ZNKSkpdpcBAAAAIEhs3rxZrVu3rnAfW4PTvHnz9OSTT2rRokVKT0/Xxx9/rPPPP/+Q+//444+65557tGbNGuXl5alt27a6/vrrdfvtt1f5NaOjoyWZDycmJuZw3wIAAACABiorK0spKSmBjFARW4NTbm6uevfurauvvloXXnhhpftHRUXp5ptvVq9evRQVFaUff/xR119/vaKiojR27NgqvWbJ8LyYmBiCEwAAAIAqTeFxWJZl1UMtlXI4HJV2nMozcuRIRUVF6a233qrS/llZWYqNjVVmZibBCQAAADiCVScbNOhV9ZYsWaKff/5ZgwYNOuQ+hYWFysrKKnMBAAAAgOpokMGpdevWCgsLU79+/XTTTTfp2muvPeS+kydPVmxsbODCwhAAAAAAqqtBrqr3ww8/KCcnR7/++qvuvfdeHX300brsssvK3XfixImaMGFC4HbJBDAAAAA0fF6vVx6Px+4yEMTcbrdcLtdhP0+DDE7t27eXJPXs2VPbt2/XpEmTDhmcwsLCFBYWVp/lAQAAoB7k5ORoy5YtCpIp+whSDodDrVu3VpMmTQ7reRpkcNqfZVkqLCy0uwwAAADUI6/Xqy1btigyMlItWrSo0qpoOPJYlqWdO3dqy5Yt6tix42F1nmwNTjk5Ofrjjz8Ct1NTU7V06VLFx8erTZs2mjhxorZu3ao333xTkvTiiy+qTZs26tKliyRzXqd//vOfuuWWW2ypHwAAAPbweDyyLEstWrRQRESE3eUgiLVo0UIbN26Ux+NpuMFp4cKFGjJkSOB2yVyk0aNHa+rUqUpPT1daWlrgfp/Pp4kTJyo1NVUhISHq0KGDHn/8cV1//fX1XjsAAADsR6cJlamtYyRozuNUXziPEwAAQMNXUFCg1NRUtW/fXuHh4XaXgyBW0bFyxJzHCQAAADjSDR48WOPHj6/y/hs3bpTD4dDSpUvrrKbGiOAEAAAA1AOHw1HhZcyYMTV63o8++kiPPPJIlfdPSUlRenq6evToUaPXq6rGFtAa/Kp6AAAAQEOQnp4euD59+nQ98MADWrt2bWDbgYtceDweud3uSp83Pj6+WnW4XC4lJiZW6zGg4wQAAADUi8TExMAlNjZWDocjcLugoEBxcXF6//33NXjwYIWHh+vtt9/W7t27ddlll6l169aKjIxUz5499d5775V53gOH6rVr105///vf9de//lXR0dFq06aN/vOf/wTuP7ATNGfOHDkcDn377bfq16+fIiMjNXDgwDKhTpIeffRRtWzZUtHR0br22mt177336phjjqnx51FYWKhbb71VLVu2VHh4uE466SQtWLAgcP/evXs1atSowMqJHTt21Ouvvy5JKioq0s0336ykpCSFh4erXbt2mjx5co1rqQqCk43+t3Srhj87T49+vsruUgAAABo0y7KUV1Rsy6U211q75557dOutt2r16tUaNmyYCgoK1LdvX33++edasWKFxo4dqyuvvFK//fZbhc/z1FNPqV+/flqyZIluvPFG3XDDDVqzZk2Fj7nvvvv01FNPaeHChQoJCdFf//rXwH3vvPOOHnvsMT3xxBNatGiR2rRpoylTphzWe7377rv14Ycf6o033tDixYt19NFHa9iwYdqzZ48k6f7779eqVav05ZdfavXq1ZoyZYqaN28uSXruuef06aef6v3339fatWv19ttvq127dodVT2UYqmej7IJircnIVttmkXaXAgAA0KDle7zq9sDXtrz2qoeHKTK0dr5Wjx8/XiNHjiyz7c477wxcv+WWW/TVV19pxowZOv744w/5PGeeeaZuvPFGSSaMPfPMM5ozZ07gfKjleeyxxzRo0CBJ0r333quzzjpLBQUFCg8P1/PPP69rrrlGV199tSTpgQce0DfffKOcnJwavc/c3FxNmTJFU6dO1YgRIyRJr7zyimbNmqVX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jz1Wbreb47oGDvydwDFce3744QetXbu20t/LEsdweQ713awx/C4mONWT0NBQ9e3b96BW7qxZszRw4ECbqmq4LMvSzTffrI8++kjfffed2rdvX+ljdu/erc2bNyspKakeKmxcCgsLtXr1aiUlJQWGKOx/LBcVFWnu3LkcyzXw+uuvq2XLljrrrLMq3I/jt+aqcsz27dtXbre7zD7p6elasWIFx3UVlYSm9evXa/bs2WrWrFmlj1m5cqU8Hg/HdQ0c+DuBY7j2vPrqq+rbt6969+5d6b4cw6Uq+27WKH4X27QoxRFp2rRpltvttl599VVr1apV1vjx462oqChr48aNdpfW4Nxwww1WbGysNWfOHCs9PT1wycvLsyzLsrKzs6077rjD+vnnn63U1FTr+++/twYMGGC1atXKysrKsrn64HfHHXdYc+bMsTZs2GD9+uuv1tlnn21FR0cHjtXHH3/cio2NtT766CNr+fLl1mWXXWYlJSXx2VaT1+u12rRpY91zzz1ltnP8Vl92dra1ZMkSa8mSJZYk6+mnn7aWLFkSWNGtKsfsuHHjrNatW1uzZ8+2Fi9ebJ166qlW7969reLiYrveVlCp6DP2eDzWueeea7Vu3dpaunRpmd/LhYWFlmVZ1h9//GE99NBD1oIFC6zU1FTriy++sLp06WL16dOHz9iq+POt6u8EjuGKVfZ7wrIsKzMz04qMjLSmTJly0OM5hitW2Xczy2r4v4sJTvXsxRdftNq2bWuFhoZaxx57bJnls1F1ksq9vP7665ZlWVZeXp41dOhQq0WLFpbb7bbatGljjR492kpLS7O38AbikksusZKSkiy3220lJydbI0eOtFauXBm43+fzWQ8++KCVmJhohYWFWaeccoq1fPlyGytumL7++mtLkrV27doy2zl+q+/7778v93fC6NGjLcuq2jGbn59v3XzzzVZ8fLwVERFhnX322Xzm+6noM05NTT3k7+Xvv//esizLSktLs0455RQrPj7eCg0NtTp06GDdeuut1u7du+19Y0Gios+3qr8TOIYrVtnvCcuyrH//+99WRESEtW/fvoMezzFcscq+m1lWw/9d7LAsy6qjZhYAAAAANArMcQIAAACAShCcAAAAAKASBCcAAAAAqATBCQAAAAAqQXACAAAAgEoQnAAAAACgEgQnAAAAAKgEwQkAgGpwOBz65JNP7C4DAFDPCE4AgAZjzJgxcjgcB12GDx9ud2kAgEYuxO4CAACojuHDh+v1118vsy0sLMymagAARwo6TgCABiUsLEyJiYllLk2bNpVkhtFNmTJFI0aMUEREhNq3b68ZM2aUefzy5ct16qmnKiIiQs2aNdPYsWOVk5NTZp/XXntN3bt3V1hYmJKSknTzzTeXuX/Xrl264IILFBkZqY4dO+rTTz+t2zcNALAdwQkA0Kjcf//9uvDCC7Vs2TJdccUVuuyyy7R69WpJUl5enoYPH66mTZtqwYIFmjFjhmbPnl0mGE2ZMkU33XSTxo4dq+XLl+vTTz/V0UcfXeY1HnroIV188cX6/fffdeaZZ2rUqFHas2dPvb5PAED9cliWZdldBAAAVTFmzBi9/fbbCg8PL7P9nnvu0f333y+Hw6Fx48ZpypQpgftOOOEEHXvssXrppZf0yiuv6J577tHmzZsVFRUlSZo5c6bOOeccbdu2TQkJCWrVqpWuvvpqPfroo+XW4HA49H//93965JFHJEm5ubmKjo7WzJkzmWsFAI0Yc5wAAA3KkCFDygQjSYqPjw9cHzBgQJn7BgwYoKVLl0qSVq9erd69ewdCkySdeOKJ8vl8Wrt2rRwOh7Zt26bTTjutwhp69eoVuB4VFaXo6Gjt2LGjpm8JANAAEJwAAA1KVFTUQUPnKuNwOCRJlmUFrpe3T0RERJWez+12H/RYn89XrZoAAA0Lc5wAAI3Kr7/+etDtLl26SJK6deumpUuXKjc3N3D/Tz/9JKfTqU6dOik6Olrt2rXTt99+W681AwCCHx0nAECDUlhYqIyMjDLbQkJC1Lx5c0nSjBkz1K9fP5100kl65513NH/+fL366quSpFGjRunBBx/U6NGjNWnSJO3cuVO33HKLrrzySiUkJEiSJk2apHHjxqlly5YaMWKEsrOz9dNPP+mWW26p3zcKAAgqBCcAQIPy1VdfKSkpqcy2zp07a82aNZLMinfTpk3TjTfeqMTERL3zzjvq1q2bJCkyMlJff/21brvtNh133HGKjIzUhRdeqKeffjrwXKNHj1ZBQYGeeeYZ3XnnnWrevLn+8pe/1N8bBAAEJVbVAwA0Gg6HQx9//LHOP/98u0sBADQyzHECAAAAgEoQnAAAAACgEsxxAgA0Gow+BwDUFTpOAAAAAFAJghMAAAAAVILgBAAAAACVIDgBAAAAQCUITgAAAABQCYITAAAAAFSC4AQAAAAAlSA4AQAAAEAlCE4AAAAAUIn/B+b65uqAH9W8AAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Calculate and print accuracies for training and cross-validation sets\n",
    "model.eval()\n",
    "with torch.no_grad():\n",
    "    # Training set accuracy\n",
    "    tr_correct = 0\n",
    "    tr_total = 0\n",
    "    for images, labels in trLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        tr_total += labels.size(0)\n",
    "        tr_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    tr_accuracy = 100 * tr_correct / tr_total\n",
    "    \n",
    "    # test set accuracy\n",
    "    te_correct = 0\n",
    "    te_total = 0\n",
    "    for images, labels in teLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        te_total += labels.size(0)\n",
    "        te_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    te_accuracy = 100 * te_correct / te_total\n",
    "\n",
    "print(f'Accuracy on training set: {tr_accuracy:.2f}%')\n",
    "print(f'Accuracy on cross-validation set: {te_accuracy:.2f}%')\n",
    "\n",
    "# Plot training and cross-validation losses\n",
    "plt.figure(figsize=(10, 5))\n",
    "plt.plot(range(1, num_epochs+1), train_losses, label='Training Loss')\n",
    "plt.plot(range(1, num_epochs+1), te_losses, label='Testing Loss')\n",
    "plt.xlabel('Epoch')\n",
    "plt.ylabel('Loss')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "9b35f685-79a6-4918-9a57-bb8e20cf2633",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test set size: 10000\n",
      "Training set size: 60000\n",
      "Number of training samples: 43360\n",
      "Number of cross-validation samples: 10850\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "label_size = 18 # Label size\n",
    "ticklabel_size = 14 # Tick label size\n",
    "\n",
    "class FlattenTransform:\n",
    "    def __call__(self, tensor):\n",
    "        ''' \n",
    "        Flatten tensor into an 1-D vector\n",
    "        '''\n",
    "        return tensor.view(-1)\n",
    "    \n",
    "# Define a transform to normalize the data\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(),\n",
    "    FlattenTransform()\n",
    "])\n",
    "\n",
    "# Load test data from the MNIST\n",
    "testset = torchvision.datasets.MNIST(root='./Data', train=False, download=False, transform=transform)\n",
    "print(f\"Test set size: {len(testset)}\")\n",
    "\n",
    "# Load training data from the MNIST\n",
    "trainset = torchvision.datasets.MNIST(root='./Data', train=True, download=False, transform=transform)\n",
    "print(f\"Training set size: {len(trainset)}\")\n",
    "\n",
    "# Rate of trX and cvX\n",
    "tr_cv_rate = 0.8\n",
    "\n",
    "# Create a list to store indices for each class\n",
    "class_indices = [[] for _ in range(10)]  # 10 classes in MNIST\n",
    "\n",
    "# Populate class_indices\n",
    "for idx, (_, label) in enumerate(trainset):\n",
    "    class_indices[label].append(idx)\n",
    "\n",
    "# Calculate the number of samples for each class in training and validation sets\n",
    "train_size_per_class = int(tr_cv_rate * min(len(indices) for indices in class_indices))\n",
    "val_size_per_class = min(len(indices) for indices in class_indices) - train_size_per_class\n",
    "\n",
    "# Create balanced train and validation sets\n",
    "train_indices = []\n",
    "val_indices = []\n",
    "for indices in class_indices:\n",
    "    train_indices.extend(indices[:train_size_per_class])\n",
    "    val_indices.extend(indices[train_size_per_class:train_size_per_class + val_size_per_class])\n",
    "\n",
    "# Create Subset datasets\n",
    "from torch.utils.data import Subset\n",
    "trX = Subset(trainset, train_indices)\n",
    "cvX = Subset(trainset, val_indices)\n",
    "\n",
    "print(f\"Number of training samples: {len(trX)}\")\n",
    "print(f\"Number of cross-validation samples: {len(cvX)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6f46e03d-29b0-4555-94f1-977163b4665f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Input_size is 784\n",
      "tensor([[0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],\n",
      "        [1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.]])\n"
     ]
    }
   ],
   "source": [
    "batch_size = 42 # Define training batch\n",
    "\n",
    "def one_hot_collate(batch):\n",
    "    data = torch.stack([item[0] for item in batch])\n",
    "    labels = torch.tensor([item[1] for item in batch])\n",
    "    one_hot_labels = torch.zeros(labels.size(0), 10)  # 10 classes in MNIST\n",
    "    one_hot_labels.scatter_(1, labels.unsqueeze(1), 1)\n",
    "    return data, one_hot_labels\n",
    "\n",
    "trLoader = torch.utils.data.DataLoader(trX, batch_size=batch_size, shuffle=True, num_workers=0, collate_fn=one_hot_collate)\n",
    "cvLoader = torch.utils.data.DataLoader(cvX, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "teLoader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=0, collate_fn=one_hot_collate)\n",
    "\n",
    "# Get a batch of training data\n",
    "dataiter = iter(trLoader)\n",
    "data, labels = next(dataiter)\n",
    "\n",
    "input_size = data[0].numpy().shape[0]\n",
    "print(f'Input_size is {input_size}')\n",
    "print(labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "98a81ee1-8456-4293-9c90-38986089c8f3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "FNN(\n",
      "  (fc1): Linear(in_features=784, out_features=10, bias=True)\n",
      "  (relu1): ReLU()\n",
      "  (fc2): Linear(in_features=10, out_features=10, bias=True)\n",
      "  (relu2): ReLU()\n",
      "  (fc3): Linear(in_features=10, out_features=10, bias=True)\n",
      "  (softmax): Softmax(dim=1)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "import torch.nn as nn\n",
    "\n",
    "class FNN(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size, num_classes):\n",
    "        super(FNN, self).__init__()\n",
    "        self.fc1 = nn.Linear(input_size, hidden_size)\n",
    "        self.relu1 = nn.ReLU()\n",
    "        self.fc2 = nn.Linear(hidden_size, hidden_size)\n",
    "        self.relu2 = nn.ReLU()\n",
    "        self.fc3 = nn.Linear(hidden_size, num_classes)\n",
    "        self.softmax = nn.Softmax(dim=1)\n",
    "    \n",
    "    def forward(self, x):\n",
    "        x = self.fc1(x)\n",
    "        x = self.relu1(x)\n",
    "        x = self.fc2(x)\n",
    "        x = self.relu2(x)\n",
    "        x = self.fc3(x)\n",
    "        out = self.softmax(x)\n",
    "        return out\n",
    "\n",
    "# Define the model parameters\n",
    "hidden_size = 10\n",
    "num_classes = 10  # MNIST has 10 classes (digits 0-9)\n",
    "\n",
    "# Instantiate the model\n",
    "model = FNN(input_size, hidden_size, num_classes)\n",
    "print(model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "96557f1f-9af2-4bc5-94b0-7a7e293b58d2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch [1/50], Train Loss: 1.7641, CV Loss: 1.6181\n",
      "Epoch [2/50], Train Loss: 1.5928, CV Loss: 1.5872\n",
      "Epoch [3/50], Train Loss: 1.5719, CV Loss: 1.5705\n",
      "Epoch [4/50], Train Loss: 1.5589, CV Loss: 1.5642\n",
      "Epoch [5/50], Train Loss: 1.5515, CV Loss: 1.5560\n",
      "Epoch [6/50], Train Loss: 1.5461, CV Loss: 1.5541\n",
      "Epoch [7/50], Train Loss: 1.5427, CV Loss: 1.5509\n",
      "Epoch [8/50], Train Loss: 1.5388, CV Loss: 1.5491\n",
      "Epoch [9/50], Train Loss: 1.5360, CV Loss: 1.5489\n",
      "Epoch [10/50], Train Loss: 1.5342, CV Loss: 1.5460\n",
      "Epoch [11/50], Train Loss: 1.5321, CV Loss: 1.5486\n",
      "Epoch [12/50], Train Loss: 1.5311, CV Loss: 1.5468\n",
      "Epoch [13/50], Train Loss: 1.5288, CV Loss: 1.5442\n",
      "Epoch [14/50], Train Loss: 1.5277, CV Loss: 1.5430\n",
      "Epoch [15/50], Train Loss: 1.5263, CV Loss: 1.5436\n",
      "Epoch [16/50], Train Loss: 1.5257, CV Loss: 1.5426\n",
      "Epoch [17/50], Train Loss: 1.5247, CV Loss: 1.5430\n",
      "Epoch [18/50], Train Loss: 1.5237, CV Loss: 1.5433\n",
      "Epoch [19/50], Train Loss: 1.5224, CV Loss: 1.5422\n",
      "Epoch [20/50], Train Loss: 1.5224, CV Loss: 1.5417\n",
      "Epoch [21/50], Train Loss: 1.5214, CV Loss: 1.5410\n",
      "Epoch [22/50], Train Loss: 1.5203, CV Loss: 1.5399\n",
      "Epoch [23/50], Train Loss: 1.5197, CV Loss: 1.5388\n",
      "Epoch [24/50], Train Loss: 1.5191, CV Loss: 1.5405\n",
      "Epoch [25/50], Train Loss: 1.5186, CV Loss: 1.5404\n",
      "Epoch [26/50], Train Loss: 1.5182, CV Loss: 1.5392\n",
      "Epoch [27/50], Train Loss: 1.5180, CV Loss: 1.5390\n",
      "Epoch [28/50], Train Loss: 1.5171, CV Loss: 1.5404\n",
      "Epoch [29/50], Train Loss: 1.5165, CV Loss: 1.5404\n",
      "Epoch [30/50], Train Loss: 1.5161, CV Loss: 1.5386\n",
      "Epoch [31/50], Train Loss: 1.5154, CV Loss: 1.5398\n",
      "Epoch [32/50], Train Loss: 1.5151, CV Loss: 1.5401\n",
      "Epoch [33/50], Train Loss: 1.5153, CV Loss: 1.5400\n",
      "Epoch [34/50], Train Loss: 1.5145, CV Loss: 1.5384\n",
      "Epoch [35/50], Train Loss: 1.5140, CV Loss: 1.5412\n",
      "Epoch [36/50], Train Loss: 1.5136, CV Loss: 1.5417\n",
      "Epoch [37/50], Train Loss: 1.5135, CV Loss: 1.5385\n",
      "Epoch [38/50], Train Loss: 1.5132, CV Loss: 1.5411\n",
      "Epoch [39/50], Train Loss: 1.5130, CV Loss: 1.5405\n",
      "Epoch [40/50], Train Loss: 1.5126, CV Loss: 1.5390\n",
      "Epoch [41/50], Train Loss: 1.5132, CV Loss: 1.5393\n",
      "Epoch [42/50], Train Loss: 1.5123, CV Loss: 1.5422\n",
      "Epoch [43/50], Train Loss: 1.5119, CV Loss: 1.5391\n",
      "Epoch [44/50], Train Loss: 1.5115, CV Loss: 1.5409\n",
      "Epoch [45/50], Train Loss: 1.5112, CV Loss: 1.5433\n",
      "Epoch [46/50], Train Loss: 1.5108, CV Loss: 1.5389\n",
      "Epoch [47/50], Train Loss: 1.5110, CV Loss: 1.5395\n",
      "Epoch [48/50], Train Loss: 1.5105, CV Loss: 1.5412\n",
      "Epoch [49/50], Train Loss: 1.5100, CV Loss: 1.5401\n",
      "Epoch [50/50], Train Loss: 1.5104, CV Loss: 1.5389\n"
     ]
    }
   ],
   "source": [
    "# Define loss function and optimizer\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.Adam(model.parameters())\n",
    "\n",
    "# Lists to store losses\n",
    "train_losses = []\n",
    "cv_losses = []\n",
    "\n",
    "# Number of epochs\n",
    "num_epochs = 50\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    model.train()\n",
    "    batch_losses = []\n",
    "    \n",
    "    for batch_x, batch_y in trLoader:\n",
    "        # Forward pass\n",
    "        outputs = model(batch_x)\n",
    "        loss = criterion(outputs, batch_y)\n",
    "        \n",
    "        # Backward pass and optimize\n",
    "        optimizer.zero_grad()\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        \n",
    "        batch_losses.append(loss.item())\n",
    "    \n",
    "    # Calculate average training loss for this epoch\n",
    "    avg_train_loss = sum(batch_losses) / len(batch_losses)\n",
    "    train_losses.append(avg_train_loss)\n",
    "    \n",
    "    # Evaluate on cross-validation set\n",
    "    model.eval()\n",
    "    cv_batch_losses = []\n",
    "    with torch.no_grad():\n",
    "        for cv_x, cv_y in cvLoader:\n",
    "            cv_outputs = model(cv_x)\n",
    "            cv_loss = criterion(cv_outputs, cv_y)\n",
    "            cv_batch_losses.append(cv_loss.item())\n",
    "    \n",
    "    avg_cv_loss = sum(cv_batch_losses) / len(cv_batch_losses)\n",
    "    cv_losses.append(avg_cv_loss)\n",
    "    \n",
    "    print(f'Epoch [{epoch+1}/{num_epochs}], Train Loss: {avg_train_loss:.4f}, CV Loss: {avg_cv_loss:.4f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "b05c74c3-e26d-43f8-9839-e8f397e64d9c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy on training set: 95.36%\n",
      "Accuracy on cross-validation set: 92.20%\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1cAAAHUCAYAAADWedKvAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB5rklEQVR4nO3dd3wUdf7H8ffsJtlNJ6GkUEKvAtKbUgSlKIKiYDkExfPniZ6e5TyseBbUOxU9Fc9TwIqcIpx3CtIEVPCE0yAqIkiHRGp6sik7vz9md5MlAQIJ2Wx4PR+PeezszOzud5NJsu98v9/PGKZpmgIAAAAAVIkt0A0AAAAAgLqAcAUAAAAA1YBwBQAAAADVgHAFAAAAANWAcAUAAAAA1YBwBQAAAADVgHAFAAAAANWAcAUAAAAA1YBwBQAAAADVgHAF4KxhGEalllWrVlXpdaZPny7DME7rsatWraqWNtR2kydPVvPmzSt1rNvt1ltvvaVhw4apQYMGCg0NVaNGjXTJJZfo3//+t9xu95ltbBVt3LhRhmHoT3/603GP2bp1qwzD0O9///tKP29F59ngwYM1ePDgkz52586dMgxDc+fOrfTref3444+aPn26du7cWW7fqXxfq5thGLr11lsD8toA4BUS6AYAQE1Zt26d3/1HH31Un332mVauXOm3vWPHjlV6nRtvvFEjRow4rcd2795d69atq3Ib6oqCggKNHTtWS5cu1VVXXaVZs2YpMTFRBw8e1JIlS3TllVdq/vz5GjNmTKCbelxdu3ZVjx499Oabb+rxxx+X3W4vd8ycOXMkSVOmTKnSa7388stVenxl/Pjjj3rkkUc0ePDgckHqwQcf1O23337G2wAAtRXhCsBZo2/fvn73GzZsKJvNVm77sfLy8hQREVHp12nSpImaNGlyWm2MiYk5aXvOJnfeeac+/fRTvfHGG7ruuuv89l1++eW65557lJ+ff9zHFxUVyTAMhYQE9s/dlClTdMstt2jx4sW65JJL/PaVlJTozTffVI8ePdS1a9cqvU6gQ3mrVq0C+voAEGgMCwSAMgYPHqxzzjlHa9asUf/+/RUREaEbbrhBkjR//nxddNFFSkpKUnh4uDp06KA//elPys3N9XuOioZrNW/eXJdccomWLFmi7t27Kzw8XO3bt9fs2bP9jqtoWODkyZMVFRWlbdu2adSoUYqKilLTpk111113yeVy+T1+7969uuKKKxQdHa169erp2muv1fr16ys1BOzgwYO65ZZb1LFjR0VFRalRo0a64IIL9Pnnn/sd5x1S9te//lXPPvusWrRooaioKPXr109fffVVueedO3eu2rVrJ4fDoQ4dOujNN988YTu80tPT9dprr2n48OHlgpVXmzZt1KVLF0mlX7u33npLd911lxo3biyHw6Ft27ZJkmbPnq2uXbvK6XQqPj5el112mTZv3uz3fNu3b9dVV12l5ORkORwOJSQkaOjQoUpNTfUds3LlSg0ePFj169dXeHi4mjVrpnHjxikvL++47+Waa65ReHi4r4eqrKVLl2rfvn2nfJ5VpKJhgfv379f48eMVHR2t2NhYTZgwQenp6eUeu2HDBl111VVq3ry5wsPD1bx5c1199dXatWuX75i5c+fqyiuvlCQNGTLEN5TWe25VNCywoKBA06ZNU4sWLRQWFqbGjRtr6tSpysjI8Duusj8jVXHkyBHdcsstaty4scLCwtSyZUvdf//95X6O3n//ffXp00exsbGKiIhQy5Ytfd8fyRqq+thjj6ldu3YKDw9XvXr11KVLFz3//PPV1lYAwYmeKwA4Rlpamn7zm9/oj3/8o5544gnZbNb/obZu3apRo0bpjjvuUGRkpH766Sc99dRT+vrrr8sNLazIxo0bddddd+lPf/qTEhIS9Nprr2nKlClq3bq1Bg4ceMLHFhUV6dJLL9WUKVN01113ac2aNXr00UcVGxurhx56SJKUm5urIUOG6MiRI3rqqafUunVrLVmyRBMmTKjU+z5y5Igk6eGHH1ZiYqJycnK0cOFCDR48WCtWrCj3of2ll15S+/btNXPmTEnWkLBRo0Zpx44dio2NlWR9GL/++us1ZswYPfPMM8rMzNT06dPlcrl8X9fj+eyzz1RUVKSxY8dWqv1e06ZNU79+/fTKK6/IZrOpUaNGmjFjhu677z5dffXVmjFjhg4fPqzp06erX79+Wr9+vdq0aSNJGjVqlEpKSvT000+rWbNmOnTokNauXesLAjt37tTFF1+s888/X7Nnz1a9evW0b98+LVmyRIWFhcft4YyNjdW4ceM0f/58HTx4UA0bNvTtmzNnjpxOp6655hpJVT/PysrPz9ewYcO0f/9+zZgxQ23bttXHH39c4Tmxc+dOtWvXTldddZXi4+OVlpamWbNmqVevXvrxxx/VoEEDXXzxxXriiSd033336aWXXlL37t0lHb/HyjRNjR07VitWrNC0adN0/vnn67vvvtPDDz+sdevWad26dXI4HL7jq/IzcjIFBQUaMmSIfvnlFz3yyCPq0qWLPv/8c82YMUOpqan6+OOPJVnDhydMmKAJEyZo+vTpcjqd2rVrl9/X/umnn9b06dP1wAMPaODAgSoqKtJPP/1ULjACOAuZAHCWmjRpkhkZGem3bdCgQaYkc8WKFSd8rNvtNouKiszVq1ebksyNGzf69j388MPmsb9eU1JSTKfTae7atcu3LT8/34yPjzf/7//+z7fts88+MyWZn332mV87JZn//Oc//Z5z1KhRZrt27Xz3X3rpJVOSuXjxYr/j/u///s+UZM6ZM+eE7+lYxcXFZlFRkTl06FDzsssu823fsWOHKcns3LmzWVxc7Nv+9ddfm5LMefPmmaZpmiUlJWZycrLZvXt30+12+47buXOnGRoaaqakpJzw9Z988klTkrlkyZJKtdf7tRs4cKDf9qNHj5rh4eHmqFGj/Lbv3r3bdDgc5jXXXGOapmkeOnTIlGTOnDnzuK/xwQcfmJLM1NTUSrWpovY9++yzvm2HDx82HQ6Hee2111b4mFM9zwYNGmQOGjTId3/WrFmmJPNf//qX33G//e1vT3pOFBcXmzk5OWZkZKT5/PPP+7a///775c5Rr0mTJvl9X5csWWJKMp9++mm/4+bPn29KMl999VXftsr+jByPJHPq1KnH3f/KK69U+HP01FNPmZLMpUuXmqZpmn/9619NSWZGRsZxn+uSSy4xzz333JO2CcDZh2GBAHCMuLg4XXDBBeW2b9++Xddcc40SExNlt9sVGhqqQYMGSVK54WUVOffcc9WsWTPffafTqbZt2/oNuzoewzA0evRov21dunTxe+zq1asVHR1drpjG1VdffdLn93rllVfUvXt3OZ1OhYSEKDQ0VCtWrKjw/V188cV+xRm8w/O8bdqyZYv279+va665xm+YZEpKivr371/pNp2qcePG+d1ft26d8vPzNXnyZL/tTZs21QUXXKAVK1ZIkuLj49WqVSv95S9/0bPPPqtvv/22XCXCc889V2FhYbrpppv0xhtvaPv27eVev6SkRMXFxb7F+xyDBg1Sq1at/IYGvvPOO3K5XH5Dzqp6npX12WefKTo6Wpde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bdpUaWlpOuecc07r9SqLEBdcqBYIAACAoJGWluZbnz9/vh566CFt2bLFty08PNzv+KKiIoWGhp70eePj40+pHXa7XYmJiaf0GNR99FzVcv9Ys13Dn1uj1z7fHuimAACAOs40TeUVFgdkMU2zUm1MTEz0LbGxsTIMw3e/oKBA9erV0z//+U8NHjxYTqdTb7/9tg4fPqyrr75aTZo0UUREhDp37qx58+b5Pe+xwwKbN2+uJ554QjfccIOio6PVrFkzvfrqq779x/YorVq1SoZhaMWKFerZs6ciIiLUv39/v+AnSY899pgaNWqk6Oho3XjjjfrTn/6kc88997S+X5Lkcrn0+9//Xo0aNZLT6dR5552n9evX+/YfPXpU1157rRo2bKjw8HC1adNGc+bMkWSV4r/11luVlJQkp9Op5s2ba8aMGafdFtBzVesdzSvUll+ztS8jP9BNAQAAdVx+UYk6PvRpQF77xz8PV0RY9Xw0vffee/XMM89ozpw5cjgcKigoUI8ePXTvvfcqJiZGH3/8sSZOnKiWLVuqT58+x32eZ555Ro8++qjuu+8+ffDBB/rd736ngQMHqn379sd9zP33369nnnlGDRs21M0336wbbrhBX375pSTpnXfe0eOPP66XX35ZAwYM0HvvvadnnnlGLVq0OO33+sc//lELFizQG2+8oZSUFD399NMaPny4tm3bpvj4eD344IP68ccftXjxYjVo0EDbtm1Tfr71ufKFF17QRx99pH/+859q1qyZ9uzZoz179px2W0C4qvWinVY3dlZ+cYBbAgAAEBzuuOMOXX755X7b7r77bt/6bbfdpiVLluj9998/YbgaNWqUbrnlFklWYHvuuee0atWqE4arxx9/XIMGDZIk/elPf9LFF1+sgoICOZ1O/e1vf9OUKVN0/fXXS5IeeughLV26VDk5Oaf1PnNzczVr1izNnTtXI0eOlCT94x//0LJly/T666/rnnvu0e7du9WtWzf17NlTktUj57V79261adNG5513ngzDUEpKymm1A6UIV7VcTLj1LcouKApwSwAAQF0XHmrXj38eHrDXri7eIOFVUlKiJ598UvPnz9e+ffvkcrnkcrkUGRl5wufp0qWLb907/PDAgQOVfkxSUpIk6cCBA2rWrJm2bNniC2tevXv31sqVKyv1vo71yy+/qKioSAMGDPBtCw0NVe/e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pdGjRysuLk6RkZHq1KmTPvnkk9NuS2WEnNFnP4O8XYhjx4712963b1/17dvXd3/AgAHq3r27/va3v+mFF16o8LmmTZumO++803c/KyurVgUsSrEDAIAaUZQnPZEcmNe+b78UFnnSw44cOaIlS5bo8ccfV2Rk+eOPHWL28MMPa8aMGXruuedkt9u1cOFC3X777Zo5c6aGDRum//znP7r++uvVpEkTDRkyRB988IGee+45vffee+rUqZPS09O1ceNGSdKGDRv0+9//Xm+99Zb69++vI0eO6PPPP6+wnSEhIbruuus0d+5cPfTQQzIMQ5L0/vvvq7CwUNdee63y8vLUo0cP3XvvvYqJidHHH3+siRMnqmXLlurTp89JvxZut1uXX365GjRooK+++kpZWVl+87O8oqOjNXfuXCUnJ2vTpk367W9/q+joaP3xj3/UhAkT9P3332vJkiVavny5JGsqzrHy8vI0YsQI9e3bV+vXr9eBAwd044036tZbb/ULkJ999pmSkpL02Wefadu2bZowYYLOPfdc/fa3vz3p+zmWaZoaO3asIiMjtXr1ahUXF+uWW27RhAkTtGrVKknStddeq27dumnWrFmy2+1KTU1VaKjVMTF16lQVFhZqzZo1ioyM1I8//qioqKhTbsepCMpwZZqmZs+erYkTJyosLOyEx9psNvXq1euEPVcOh6NWd3lyEWEAAADLtm3bZJqm2rdvX6njr7nmGt1www1+9ydPnqxbbrlFkny9XX/96181ZMgQ7d69W4mJiRo2bJhCQ0PVrFkz9e7dW5LVixIZGalLLrlE0dHRSklJUbdu3Y772jfccIP+8pe/aNWqVRoyZIgka0jg5Zdfrri4OMXFxenuu+/2HX/bbbdpyZIlev/99ysVrpYvX67Nmzdr586datKkiSTpiSeeKDdP6oEHHvCtN2/eXHfddZfmz5+vP/7xjwoPD1dUVJRCQkJOWKfgnXfeUX5+vt58801fqH3xxRc1evRoPfXUU0pISJAkxcXF6cUXX5Tdblf79u118cUXa8WKFacVrpYvX67vvvtOO3bs8HV8vPXWW+rUqZPWr1+vXr16affu3brnnnt850ObNm18j9+9e7fGjRunzp07S5Jatmx5ym04VUEZrlavXq1t27ZpypQpJz3WNE2lpqb6vqjBKCbc+jZl03MFAADOpNAIqwcpUK9dCaZn+KC3J+hkevbs6Xd/8+bN5QpCDBgwQM8//7wk6corr9TMmTPVsmVLjRgxQqNGjdLo0aMVEhKiCy+8UCkpKb59I0aM0GWXXaaIiAi98847+r//+z/fcy5evFjnn3+++vfvr9mzZ2vIkCH65Zdf9Pnnn2vp0qWSpJKSEj355JOaP3++9u3bJ5fLJZfLVWGPXEU2b96sZs2a+YKVJPXr16/ccR988IFmzpypbdu2KScnR8XFxYqJianUa5R9ra5du/q1bcCAAXK73dqyZYsvXHXq1El2u913TFJSkjZt2nRKr1X2NZs2beo3oqxjx46qV6+eNm/erF69eunOO+/UjTfeqLfeekvDhg3TlVdeqVatWkmSfv/73+t3v/udli5dqmHDhmncuHHq0qXLabWlsgI65yonJ0epqalKTU2VJO3YsUOpqanavXu3JGu43nXXXVfuca+//rr69Omjc845p9y+Rx55RJ9++qm2b9+u1NRUTZkyRampqbr55pvP6Hs5k7wFLVzFbrmKSwLcGgAAUGcZhjU0LxBLJcNSmzZtZBiGNm/eXKnjKwoqxwYz0zR925o2baotW7bopZdeUnh4uG655RYNHDhQRUVFio6O1jfffKN58+YpKSlJDz30kLp27aqMjAxdeumlvs+1qampvlA3ZcoULViwQFlZWZozZ45SUlI0dOhQSdIzzzyj5557Tn/84x+1cuVKpaamavjw4SosLKzUezMrmKd27Hv76quvdNVVV2nkyJH6z3/+o2+//Vb3339/pV+joq/RiV7TOySv7D63231Kr3Wy1yy7ffr06frhhx908cUXa+XKlerYsaMWLlwoSbrxxhu1fft2TZw4UZs2bVLPnj31t7/97bTaUlkBDVcbNmxQt27dfN2pd955p7p166aHHnpIklW0whu0vDIzM7VgwYLj9lplZGTopptuUocOHXTRRRdp3759WrNmja87NxhFO0J8v28oagEAAM5m8fHxGj58uF566SXl5uaW25+RkXHCx3fo0EFffPGF37a1a9eqQ4cOvvvh4eG69NJL9cILL2jVqlVat26dr/clJCREw4YN09NPP63vvvtOO3fu1MqVKxUdHa3WrVv7lvDwcEnS+PHjZbfb9e677+qNN97Q9ddf7wsGn3/+ucaMGaPf/OY36tq1q1q2bHnCqSzH6tixo3bv3q39+0t7G9et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AAAAAFQDwhUAAAAAVAPCFQAAAABUA8JVDXn55ZfVokULOZ1O9ejRQ59//nmgm4RaaM2aNRo9erSSk5NlGIYWLVrkt980TU2fPl3JyckKDw/X4MGD9cMPPwSmsahVZsyYoV69eik6OlqNGjXS2LFjtWXLFr9jOH9wPLNmzVKXLl0UExOjmJgY9evXT4sXL/bt59xBZc2YMUOGYeiOO+7wbeP8wfFMnz5dhmH4LYmJib79wXjuEK5qwPz583XHHXfo/vvv17fffqvzzz9fI0eO1O7duwPdNNQyubm56tq1q1588cUK9z/99NN69tln9eKLL2r9+vVKTEzUhRdeqOzs7BpuKWqb1atXa+rUqfrqq6+0bNkyFRcX66KLLlJubq7vGM4fHE+TJk305JNPasOGDdqwYYMuuOACjRkzxvchhnMHlbF+/Xq9+uqr6tKli992zh+cSKdOnZSWluZbNm3a5NsXlOeOiTOud+/e5s033+y3rX379uaf/vSnALUIwUCSuXDhQt99t9ttJiYmmk8++aRvW0FBgRkbG2u+8sorAWgharMDBw6YkszVq1ebpsn5g1MXFxdnvvbaa5w7qJTs7GyzTZs25rJly8xBgwaZt99+u2ma/O7BiT388MNm165dK9wXrOcOPVdnWGFhof73v//poosu8tt+0UUXae3atQFqFYLRjh07lJ6e7ncuORwODRo0iHMJ5WRmZkqS4uPjJXH+oPJKSkr03nvvKTc3V/369ePcQaVMnTpVF198sYYNG+a3nfMHJ7N161YlJyerRYsWuuqqq7R9+3ZJwXvuhAS6AXXdoUOHVFJSooSEBL/tCQkJSk9PD1CrEIy850tF59KuXbsC0STUUqZp6s4779R5552nc845RxLnD05u06ZN6tevnwoKChQVFaWFCxeqY8eOvg8xnDs4nvfee0/ffPON1q9fX24fv3twIn369NGbb76ptm3b6tdff9Vjjz2m/v3764cffgjac4dwVUMMw/C7b5pmuW1AZXAu4WRuvfVWfffdd/riiy/K7eP8wfG0a9dOqampysjI0IIFCzRp0iStXr3at59zBxXZs2ePbr/9di1dulROp/O4x3H+oCIjR470rXfu3Fn9+vVTq1at9MYbb6hv376Sgu/cYVjgGdagQQPZ7fZyvVQHDhwol8SBE/FWz+Fcwoncdttt+uijj/TZZ5+pSZMmvu2cPziZsLAwtW7dWj179tSMGTPUtWtXPf/885w7OKH//e9/OnDggHr06KGQkBCFhIRo9erVeuGFFxQSEuI7Rzh/UBmRkZHq3Lmztm7dGrS/ewhXZ1hYWJh69OihZcuW+W1ftmyZ+vfvH6BWIRi1aNFCiYmJfudSYWGhVq9ezbkEmaapW2+9VR9++KFWrlypFi1a+O3n/MGpMk1TLpeLcwcnNHToUG3atEmpqam+pWfPnrr22muVmpqqli1bcv6g0lwulzZv3qykpKSg/d3DsMAacOedd2rixInq2bOn+vXrp1dffVW7d+/WzTffHOimoZbJycnRtm3bfPd37Nih1NRUxcfHq1mzZrrjjjv0xBNPqE2bNmrTpo2eeOIJRURE6Jprrglgq1EbTJ06Ve+++67+9a9/KTo62vefvtjYWIWHh/uuO8P5g4rcd999GjlypJo2bars7Gy99957WrVqlZYsWcK5gxOKjo72ze30ioyMVP369X3bOX9wPHfffbdGjx6tZs2a6cCBA3rssceUlZWlSZMmBe/vnoDVKTzLvPTSS2ZKSooZFhZmdu/e3VceGSjrs88+MyWVWyZNmmSaplWW9OGHHzYTExNNh8NhDhw40Ny0aVNgG41aoaLzRpI5Z84c3zGcPzieG264wfc3qmHDhubQoUPNpUuX+vZz7uBUlC3FbpqcPzi+CRMmmElJSWZoaKiZnJxsXn755eYPP/zg2x+M545hmqYZoFwHAAAAAHUGc64AAAAAoBoQrgAAAACgGhCuAAAAAKAaEK4AAAAAoBoQrgAAAACgGhCuAAAAAKAaEK4AAAAAoBoQrgAAAACgGhCuAACoZoZhaNGiRYFuBgCghhGuAAB1yuTJk2UYRrllxIgRgW4aAKCOCwl0AwAAqG4jRozQnDlz/LY5HI4AtQYAcLag5woAUOc4HA4lJib6LXFxcZKsIXuzZs3SyJEjFR4erhYtWuj999/3e/ymTZt0wQUXKDw8XPXr19dNN92knJwcv2Nmz56tTp06yeFwKCkpSbfeeqvf/kOHDumyyy5TRESE2rRpo48++ujMvmkAQMARrgAAZ50HH3xQ48aN08aNG/Wb3/xGV199tTZv3ixJysvL04gRIxQXF6f169fr/fff1/Lly/3C06xZszR16lTddNNN2rRpkz766CO1bt3a7zUeeeQRjR8/Xt99951GjRqla6+9VkeOHKnR9wkAqFmGaZpmoBsBAEB1mTx5st5++205nU6/7ffee68efPBBGYahm2++WbNmzfLt69u3r7p3766XX35Z//jHP3Tvvfdqz549ioyMlCR98sknGj16tPbv36+EhAQ1btxY119/vR577LEK22AYhh544AE9+uijkqTc3FxFR0frk08+Ye4XANRhzLkCANQ5Q4YM8QtPkhQfH+9b79evn9++fv36KTU1VZK0efNmde3a1ResJGnAgAFyu93asmWLDMPQ/v37NXTo0BO2oUuXLr71yMhIRUdH68CBA6f7lgAAQYBwBQCocyIjI8sN0zsZwzAkSaZp+tYrOiY8PLxSzxcaGlrusW63+5TaBAAILsy5AgCcdb766qty99u3by9J6tixo1JTU5Wbm+vb/+WXX8pms6lt27aKjo5W8+bNtWLFihptMwCg9qPnCgBQ57hcLqWnp/ttCwkJUYMGDSRJ77//vnr27KnzzjtP77zzjr7++mu9/vrrkqRrr71WDz/8sCZNmqTp06fr4MGDuu222zRx4kQlJCRIkqZPn66bb75ZjRo10siRI5Wdna0vv/xSt912W82+UQBArUK4AgDUOUuWLFFSUpLftnbt2umnn36SZFXye++993TLLbcoMTFR77zzjjp27ChJioiI0Keffqrbb79dvXr1UkREhMaNG6dnn33W91yTJk1SQUGBnnvuOd19991q0KCBrrjiipp7gwCAWolqgQCAs4phGFq4cKHGjh0b6KYAAOoY5lwBAAAAQDUgXAEAAABANWDOFQDgrMJoeADAmULPFQAAAABUA8IVAAAAAFQDwhUAAAAAVAPCFQAAAABUA8IVAAAAAFQDwhUAAAAAVAPCFQAAAABUA8IVAAAAAFSD/wf8unDVyCTRSwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Calculate and print accuracies for training and cross-validation sets\n",
    "model.eval()\n",
    "with torch.no_grad():\n",
    "    # Training set accuracy\n",
    "    tr_correct = 0\n",
    "    tr_total = 0\n",
    "    for images, labels in trLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        tr_total += labels.size(0)\n",
    "        tr_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    tr_accuracy = 100 * tr_correct / tr_total\n",
    "    \n",
    "    # Cross-validation set accuracy\n",
    "    cv_correct = 0\n",
    "    cv_total = 0\n",
    "    for images, labels in cvLoader:\n",
    "        outputs = model(images)\n",
    "        _, predicted = torch.max(outputs, 1)\n",
    "        _, true_labels = torch.max(labels, 1)\n",
    "        cv_total += labels.size(0)\n",
    "        cv_correct += (predicted == true_labels).sum().item()\n",
    "    \n",
    "    cv_accuracy = 100 * cv_correct / cv_total\n",
    "\n",
    "print(f'Accuracy on training set: {tr_accuracy:.2f}%')\n",
    "print(f'Accuracy on cross-validation set: {cv_accuracy:.2f}%')\n",
    "\n",
    "# Plot training and cross-validation losses\n",
    "plt.figure(figsize=(10, 5))\n",
    "plt.plot(range(1, num_epochs+1), train_losses, label='Training Loss')\n",
    "plt.plot(range(1, num_epochs+1), cv_losses, label='Cross-Validation Loss')\n",
    "plt.xlabel('Epoch')\n",
    "plt.ylabel('Loss')\n",
    "plt.title('Training and Cross-Validation Loss')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c4c237e1-f87e-454b-b6a4-046df6005b18",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
